package com.starhub.common.security.filter;

import com.starhub.common.security.config.SecurityWhiteList;
import com.starhub.common.security.util.SqlInjectionUtil;
import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.FilterConfig;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.annotation.WebFilter;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.util.ContentCachingRequestWrapper;

import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.util.Enumeration;
import java.util.Map;

/**
 * 安全过滤器
 * @version: V1.0
 * @author: liuhf
 * @time 2025-06-06
 */
@Slf4j
//@Component
//@WebFilter(urlPatterns = "/*")
//@Order(1)
public class SecurityFilter implements Filter {

    @Autowired
    private SecurityWhiteList securityWhiteList;

    private final AntPathMatcher pathMatcher = new AntPathMatcher();

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        log.info("SecurityFilter initialized");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;

        String requestURI = httpRequest.getRequestURI();
        String clientIP = getClientIP(httpRequest);

        // 检查是否在白名单中
        if (isInWhiteList(requestURI, clientIP)) {
            chain.doFilter(request, response);
            return;
        }

        // 包装请求以支持多次读取
        ContentCachingRequestWrapper wrappedRequest = new ContentCachingRequestWrapper(httpRequest);

        // 检查请求参数
        if (checkRequestParameters(wrappedRequest)) {
            httpResponse.sendError(HttpServletResponse.SC_FORBIDDEN, "Potential SQL injection detected");
            return;
        }

        chain.doFilter(wrappedRequest, response);
    }

    @Override
    public void destroy() {
        log.info("SecurityFilter destroyed");
    }

    /**
     * 检查请求参数是否存在SQL注入风险
     * @param request HTTP请求
     * @return true-存在风险 false-不存在风险
     */
    private boolean checkRequestParameters(HttpServletRequest request) {
        // 检查URL参数
        Map<String, String[]> parameterMap = request.getParameterMap();
        for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
            if (SqlInjectionUtil.containsSqlInjection(entry.getValue())) {
                log.warn("SQL injection detected in parameter: {} = {}", entry.getKey(), entry.getValue());
                return true;
            }
        }

        // 检查请求头
        /*Enumeration<String> headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String headerName = headerNames.nextElement();
            String headerValue = request.getHeader(headerName);
            if (SqlInjectionUtil.containsSqlInjection(headerValue)) {
                log.warn("SQL injection detected in header: {} = {}", headerName, headerValue);
                return true;
            }
        }*/

        return false;
    }

    /**
     * 检查是否在白名单中
     * @param requestURI 请求URI
     * @param clientIP 客户端IP
     * @return true-在白名单中 false-不在白名单中
     */
    private boolean isInWhiteList(String requestURI, String clientIP) {
        // 检查URL白名单
        for (String whiteListUrl : securityWhiteList.getUrlList()) {
            if (pathMatcher.match(whiteListUrl, requestURI)) {
                return true;
            }
        }

        // 检查IP白名单
        return securityWhiteList.getIpList().contains(clientIP);
    }

    /**
     * 获取客户端真实IP
     * @param request HTTP请求
     * @return 客户端IP
     */
    private String getClientIP(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }
}
